package com.conselheiro.web.persistence.webdao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.apache.log4j.Logger;

import com.conselheiro.web.entidade.Identificavel;
import com.conselheiro.web.persistence.GerenciadorJPA;


public abstract class WebDAO<T extends Identificavel> {

	private Logger logger = Logger.getLogger(getClass());
	private EntityManagerFactory entityManagerFactory = GerenciadorJPA.getScopedEntityManagerFactory();

	public void adicionar(T novo){
		EntityManager entityManager = getEntityManager();
		try {
			EntityTransaction transaction = entityManager.getTransaction();
			transaction.begin();
			entityManager.persist(novo);
			transaction.commit();
			logger.info("Entidade salva com sucesso: " + novo);
		} finally {
			entityManager.close();
		}
	}

	public void atualizar(T novo) {
		EntityManager entityManager = getEntityManager();
		try {
			EntityTransaction transaction = entityManager.getTransaction();
			transaction.begin();
			entityManager.merge(novo);
			transaction.commit();
			logger.info("Entidade atualizada com sucesso: " + novo);
		} finally {
			entityManager.close();
		}

	}

	public void remover(T t) {
		remover(t.getId());
		logger.info("Entidade removida com sucesso: " + t);
	}

	public void remover(long id) {
		EntityManager entityManager = getEntityManager();
		try {
			EntityTransaction transaction = entityManager.getTransaction();
			transaction.begin();
			entityManager.remove(entityManager.find(getClasse(), id));
			transaction.commit();
		} finally {
			entityManager.close();
		}
	}

	public List<T> recuperar() {
		return recuperar(true);
	}

	public List<T> recuperar(boolean desc) {
		return recuperar(0, -1, desc);
	}

	@SuppressWarnings("unchecked")
	public List<T> recuperar(int firstResult, int maxResults, boolean desc) {
		EntityManager entityManager = getEntityManager();
		try {
			String order = desc ? "desc" : "asc";
			Query query = entityManager
					.createQuery("select o from " + getClasse().getSimpleName()
							+ " o order by o.id " + order);

			if (firstResult >= 0 && maxResults >= 0) {
				query.setFirstResult(firstResult);
				query.setMaxResults(maxResults);
			}
			return query.getResultList();
		} finally {
			entityManager.close();
		}
	}
	
	public T recuperar(long id) {
		EntityManager entityManager = getEntityManager();
		try {
			return entityManager.find(getClasse(), id);
		} finally {
			entityManager.close();
		}
	}

	@SuppressWarnings("unchecked")
	public List<T> recuperarAutoCompletar(boolean exato, String order,
			String key, String value, boolean asc) {
		EntityManager entityManager = getEntityManager();
		try {
			value = exato ? "'" + value + "%'" : "'%" + value + "%'";
			Query query = entityManager.createQuery("SELECT o FROM "
					+ getClasse().getSimpleName() + " o WHERE " + key
					+ " LIKE " + value + " ORDER BY " + order + " "
					+ (asc ? "ASC" : "DESC"));

			return query.getResultList();
		} finally {
			entityManager.close();
		}
	}

	public String quote(String string) {
		return string == null ? null : string.replace("'", "''");
	}

	protected abstract Class<T> getClasse();

	protected EntityManager getEntityManager() {
		return entityManagerFactory.createEntityManager();
	}

}
